import dxui from '../dxmodules/dxUi.js'
import dxMap from '../dxmodules/dxMap.js'
import log from '../dxmodules/dxLogger.js'
import net from '../dxmodules/dxNet.js'
import viewUtils from './view/viewUtils.js'
import i18n from './view/i18n.js'
import pinyin from './view/pinyin/pinyin.js'
import mainView from './view/mainView.js'
import idleView from './view/idleView.js'
import topView from './view/topView.js'
import appView from './view/appView.js'
import pwdView from './view/pwdView.js'
import newPwdView from './view/config/newPwdView.js'
import identityVerificationView from './view/config/identityVerificationView.js'
import configView from './view/config/configView.js'
import cloudCertView from './view/config/menu/cloudCertView.js'
import doorControlView from './view/config/menu/doorControlView.js'
import helpView from './view/config/menu/helpView.js'
import networkSettingView from './view/config/menu/networkSettingView.js'
import systemSettingView from './view/config/menu/systemSettingView.js'
import deviceInfoView from './view/config/menu/deviceInfoView.js'
import factoryTestView from './view/config/menu/factoryTestView.js'
import localUserView from './view/config/menu/localUserView.js'
import recordQueryView from './view/config/menu/recordQueryView.js'
import voiceBroadcastView from './view/config/menu/voiceBroadcastView.js'
import localUserAddView from './view/config/menu/localUser/localUserAddView.js'
import faceEnterView from './view/config/menu/localUser/faceEnterView.js'
import displaySettingView from './view/config/menu/systemSetting/displaySettingView.js'
import faceRecognitionSettingView from './view/config/menu/systemSetting/faceRecognitionSettingView.js'
import swipeCardRecognitionSettingView from './view/config/menu/systemSetting/swipeCardRecognitionSettingView.js'
import passLogSettingView from './view/config/menu/systemSetting/passLogSettingView.js'
import passwordOpenDoorSettingView from './view/config/menu/systemSetting/passwordOpenDoorSettingView.js'
import passwordManagementView from './view/config/menu/systemSetting/passwordManagementView.js'
import timeSettingView from './view/config/menu/systemSetting/timeSettingView.js'
import systemInfoView from './view/config/menu/deviceInfo/systemInfoView.js'
import dataCapacityInfoView from './view/config/menu/deviceInfo/dataCapacityInfoView.js'
import recordQueryDetailView from './view/config/menu/recordQuery/recordQueryDetailView.js'
import std from '../dxmodules/dxStd.js'
import bus from '../dxmodules/dxEventBus.js'
import driver from './driver.js'
import config from '../dxmodules/dxConfig.js'
import common from '../dxmodules/dxCommon.js'
import configService from './service/configService.js'
import sqliteService from './service/sqliteService.js'
import faceService from './service/faceService.js'
const screen = {}

screen.screenSize = {
    width: 800,
    height: 1280
}

// UI context
const context = {}

// The initialization method, called in main.js, can only be called once.
screen.init = function () {
    const loadMethod = dxui.loadMain
    dxui.loadMain = function (view) {
        if (screen.screenNow && screen.screenNow.id == view.id) {
            return
        }
        screen.screenNow = view
        pinyin.hide(true)
        loadMethod.call(dxui, view)
    }

    dxui.init({ orientation: 0 }, context);
    // Initialize all components
    pinyin.init(800, 400)

    viewUtils.confirmInit()

    mainView.init()
    idleView.init()
    topView.init()
    appView.init()
    pwdView.init()
    newPwdView.init()
    identityVerificationView.init()
    configView.init()

    cloudCertView.init()
    doorControlView.init()
    helpView.init()
    networkSettingView.init()
    systemSettingView.init()
    deviceInfoView.init()
    factoryTestView.init()
    localUserView.init()
    recordQueryView.init()
    voiceBroadcastView.init()

    localUserAddView.init()
    faceEnterView.init()

    displaySettingView.init()
    faceRecognitionSettingView.init()
    swipeCardRecognitionSettingView.init()
    passLogSettingView.init()
    passwordOpenDoorSettingView.init()
    passwordManagementView.init()
    timeSettingView.init()

    systemInfoView.init()
    dataCapacityInfoView.init()
    recordQueryDetailView.init()

    // Set language
    // i18n.setLanguage("en-US")
    i18n.setLanguage(config.get("base.language"))

    dxui.loadMain(mainView.screenMain)

    // Start screen saver timer
    idleTimerStart()

    // bus event
    busEvents()

    // Get click coordinates in real time
    getClickPoint()

    // Hide keyboard
    hidePinyin()

    // Face tracking box
    faceTrackingBox()
}

function faceTrackingBox() {
    std.setInterval(() => {
        let data = driver.face.getTrackingBox()
        try {
            if (data) {
                data = JSON.parse(data)
                // Maximum of 10 people
                if (data.type == "track" && data.faces.length <= 10) {
                    for (let i = 0; i < data.faces.length; i++) {
                        let item = data.faces[i]
                        screen.trackUpdate({ w: item.rect_render[2] - item.rect_render[0], h: item.rect_render[3] - item.rect_render[1], x: item.rect_render[0], y: item.rect_render[1] }, item.id, item.is_living)
                    }
                }
            }
        } catch (error) {
            log.info('screen.faceTrackingBox:', data);
            log.error("screen.faceTrackingBox:", error)
        }
    }, 110)
}

let changedClickPoint
let lastClickPoint = { x: 0, y: 0 }
let clickPoint
// Get click coordinates in real time
function getClickPoint() {
    const indev = NativeObject.APP.NativeComponents.NativeIndev
    std.setInterval(() => {
        clickPoint = {
            x: Math.abs(800 - indev.lvIndevGetPointVg().x),
            y: indev.lvIndevGetPointVg().y
        }

        if (lastClickPoint.x != clickPoint.x || lastClickPoint.y != clickPoint.y) {
            changedClickPoint = clickPoint
        } else {
            changedClickPoint = null
        }

        lastClickPoint = clickPoint
    }, 5)
}

function hidePinyin() {
    let showPoint
    const hideMethod = pinyin.hide
    const showMethod = pinyin.show
    // Lock
    let lock = false
    pinyin.hide = function (isForce) {
        if (isForce) {
            hideMethod.call(pinyin)
            lock = false
            return
        }
        if (lock) {
            return
        }
        lock = true
        hideMethod.call(pinyin)
        lock = false
    }
    pinyin.show = function (...args) {
        if (lock) {
            return
        }
        lock = true
        showMethod.call(pinyin, ...args)
        showPoint = clickPoint
        lock = false
    }
    std.setInterval(() => {
        if (showPoint && (Math.abs(showPoint.x - clickPoint.x) > 5 && Math.abs(showPoint.y - clickPoint.y) > 5)) {
            if (clickPoint.y < (1280 - (pinyin.getMode() == 1 ? 400 + 70 : 400))) {
                let defocus = dxMap.get("INPUT_KEYBOARD").get("defocus")
                if (defocus == "defocus") {
                    dxMap.get("INPUT_KEYBOARD").del("defocus")
                    showPoint = null
                    pinyin.hide()
                }
            }
        }
    }, 5)
}

class ScreenManager {
    constructor(callbacks = {}) {
        this.timers = {
            screenSaver: null,
            screenOff: null
        };

        // Default configuration
        this.config = {
            screenSaverDelay: 0, // Screen saver delay (milliseconds)
            screenOffDelay: 0    // Screen off delay (milliseconds)
        };

        // callback function
        this.callbacks = {
            onScreenSaverStart: callbacks.onScreenSaverStart || (() => { }),
            onScreenSaverEnd: callbacks.onScreenSaverEnd || (() => { }),
            onScreenOff: callbacks.onScreenOff || (() => { }),
            onScreenOn: callbacks.onScreenOn || (() => { })
        };

        this.resetTimers = this.resetTimers.bind(this);
    }

    // Configuration time
    configure({ screenSaverDelay = 0, screenOffDelay = 0 }) {
        this.config.screenSaverDelay = screenSaverDelay;
        this.config.screenOffDelay = screenOffDelay;
        this.resetTimers();
    }

    // Reset Timer
    resetTimers() {
        // Clear existing timers
        if (this.timers.screenSaver) {
            std.clearTimeout(this.timers.screenSaver);
        }
        if (this.timers.screenOff) {
            std.clearTimeout(this.timers.screenOff);
        }

        // Exit the current state
        this.exitScreenStates();

        // Set a new timer
        if (this.config.screenOffDelay > 0) {
            this.timers.screenOff = std.setTimeout(() => {
                this.enterScreenOff();
            }, this.config.screenOffDelay);
        }

        // The screen saver timer is only set when the screen-off time is longer than the screen saver duration.
        if (this.config.screenSaverDelay > 0 &&
            (this.config.screenSaverDelay < this.config.screenOffDelay || this.config.screenOffDelay == 0)) {
            this.timers.screenSaver = std.setTimeout(() => {
                this.enterScreenSaver();
            }, this.config.screenSaverDelay);
        }
    }

    // Enter screen saver mode
    enterScreenSaver() {
        const mapUI = dxMap.get("UI")
        if (!mapUI.get("isScreenOff")) {
            mapUI.put("isScreenSaver", true)
            this.callbacks.onScreenSaverStart();
        }
    }

    // Enter screen-off state
    enterScreenOff() {
        const mapUI = dxMap.get("UI")
        mapUI.put("isScreenOff", true)
        mapUI.put("isScreenSaver", false)
        this.callbacks.onScreenOff();
    }

    // Exit all screen states
    exitScreenStates() {
        const mapUI = dxMap.get("UI")
        const previousState = { isScreenOff: mapUI.get("isScreenOff"), isScreenSaver: mapUI.get("isScreenSaver") };
        mapUI.put("isScreenOff", false)
        mapUI.put("isScreenSaver", false)
        // If the state changes, the corresponding callback is triggered.
        if (previousState.isScreenSaver) {
            this.callbacks.onScreenSaverEnd();
        }
        if (previousState.isScreenOff) {
            this.callbacks.onScreenOn();
        }
    }

    // Get the current state
    getState() {
        const mapUI = dxMap.get("UI")
        return { isScreenOff: mapUI.get("isScreenOff"), isScreenSaver: mapUI.get("isScreenSaver") };
    }

    // Clean up resources
    destroy() {
        if (this.timers.screenSaver) {
            std.clearTimeout(this.timers.screenSaver);
        }
        if (this.timers.screenOff) {
            std.clearTimeout(this.timers.screenOff);
        }
    }
}

let screenManager
function idleTimerStart() {
    // Create an instance and pass in the callback function.
    screenManager = new ScreenManager({
        onScreenSaverStart: () => {
            screen.enterIdle()
        },
        onScreenSaverEnd: () => {
            screen.exitIdle(true)
        },
        onScreenOff: () => {
            dxMap.get("screenOff").put("status", 1)
            screen.screenNow.hide()
            topView.screenMain.hide()
        },
        onScreenOn: () => {
            screen.exitIdle(true)
            dxMap.get("screenOff").put("status", 0)
            screen.screenNow.show()
            topView.screenMain.show()
        }
    });

    // Configuration time (milliseconds)
    screenManager.configure({
        // screenSaverDelay: 10000,  // screensaver
        // screenOffDelay: 5000     // Screen off
        screenSaverDelay: config.get("base.screensaver") * 60 * 1000,  // screensaver
        screenOffDelay: config.get("base.screenOff") * 60 * 1000     // Screen off
    });

    // Detecting user touch
    let touchCount = 0
    std.setInterval(() => {
        let count = dxui.Utils.GG.NativeDisp.lvDispGetInactiveTime()
        if (count < touchCount) {
            screenManager.resetTimers();
        }
        touchCount = count
    }, 100);
}

screen.screenManagerRefresh = function () {
    screenManager.configure({
        screenSaverDelay: config.get("base.screensaver") * 60 * 1000,  // screensaver
        screenOffDelay: config.get("base.screenOff") * 60 * 1000     // Screen off
    });
    screenManager.resetTimers();
}

let enterIdleTimer
// Enter screensaver
screen.enterIdle = function () {
    // A 1-second delay is added to prevent simultaneous activation and deactivation of the screensaver. If the deactivation is not triggered within 1 second, it is assumed that the screensaver has been activated.
    enterIdleTimer = std.setTimeout(() => {
        if (idleView.screenMain.isHide()) {
            viewUtils.confirmClose()
            dxui.loadMain(mainView.screenMain)
            idleView.screenMain.show()
            topView.changeTheme(false)
        }
    }, 1000)
}

// Exit screensaver
screen.exitIdle = function (isSelf) {
    if (enterIdleTimer) {
        std.clearTimeout(enterIdleTimer)
        enterIdleTimer = null
    }
    if (!isSelf) {
        screenManager.resetTimers();
    }
    if (!idleView.screenMain.isHide()) {
        idleView.screenMain.hide()
    }
}

screen.loop = function () {
    return dxui.handler()
}

// Cloud certificate activation: 0 successful, non-zero failed.
screen.nfcIdentityCardActivation = function (code) {
    return driver.eid.active(config.get("sys.sn"), config.get("sys.appVersion"), config.get("sys.mac"), code);

}

// Delete personnel
screen.deleteUser = function (user) {
    sqliteService.d1_person.deleteByUserId(user.userId)
    sqliteService.d1_permission.deleteByUserId(user.userId)
    sqliteService.d1_voucher.deleteByUserId(user.userId)
    let res = driver.face.delete(user.userId)

    return true
}

screen.updateUser = function (user) {
    //Modify personnel information
    let res = sqliteService.d1_person.updatenameAndExtraByUserId(user.userId, user.name, JSON.stringify({ type: user.type, idCard: user.idCard }))
    if (res != 0) {
        return false
    }
    //Processing credentials
    let ret
    if (user.pwd) {
        //Determine if the credentials exists in the database table.
        let pwdData = sqliteService.d1_voucher.findByCodeAndType(user.pwd, "400");
        if (pwdData.length > 0 && pwdData[0].userId != user.userId) {
            // The option to add the item failed.
            log.info("Repeat Password");
            return "localUserAddView.failPwdRepeat"
        }
        // Check if there are any updated or newly added password credentials.
        let countByuserIdAndType = sqliteService.d1_voucher.findByuserIdAndType(user.userId, "400");
        if (countByuserIdAndType.length > 0) {
            ret = sqliteService.d1_voucher.updatecodeByuserIdAndtype(user.userId, "400", user.pwd)
            if (ret != 0) {
                return false
            }
        } else {
            // Add one
            ret = sqliteService.d1_voucher.save({ keyId: std.genRandomStr(32), type: "400", code: user.pwd, userId: user.userId })
            if (ret != 0) {
                return false
            }
        }
    } else {
        // If there is no content, delete it from the database table.
        sqliteService.d1_voucher.deleteByuserIdAndtype(user.userId, "400")
    }
    if (user.card) {
        // Determine if the credentials exists in the database table.
        let cardData = sqliteService.d1_voucher.findByCodeAndType(user.card, "200");
        if (cardData.length > 0 && cardData[0].userId != user.userId) {
            // The option to add the item failed.
            log.info("Present card again");
            return "localUserAddView.failCardRepeat"
        }
        // Check if there are any updated or newly added password credentials.
        let countByuserIdAndType = sqliteService.d1_voucher.countByuserIdAndType(user.userId, "200");
        if (countByuserIdAndType > 0) {
            ret = sqliteService.d1_voucher.updatecodeByuserIdAndtype(user.userId, "200", user.card)
            if (ret != 0) {
                return false
            }
        } else {
            // Add one
            ret = sqliteService.d1_voucher.save({ keyId: std.genRandomStr(32), type: "200", code: user.card, userId: user.userId })

            if (ret != 0) {
                return false
            }
        }
    } else {
        // If there is no content, delete it from the database table.
        sqliteService.d1_voucher.deleteByuserIdAndtype(user.userId, "200")
    }
    if (user.face) {

        let findByuserIdAndType = sqliteService.d1_voucher.findByuserIdAndType(user.userId, "300");
        if (findByuserIdAndType.length <= 0) {
            let ret = driver.face.registerFaceByPicFile(user.userId, user.face)
            log.info("2. Register face,ret:", ret)
            if (ret != 0) {
                return faceService.regErrorEnum.picture[ret + '']
            }
            // After successful registration, you need to move the original images to the corresponding directory for the user account.
            let src = "/app/data/user/" + user.userId + "/register.jpg"
            std.ensurePathExists(src)
            common.systemBrief('mv ' + user.face + " " + src)

            // Add one
            ret = sqliteService.d1_voucher.save({ keyId: std.genRandomStr(32), type: "300", code: src, userId: user.userId })
            if (ret != 0) {
                return false
            }
        } else {
            // It turns out there was another incoming message; it was deleted first and then added back.
            if (findByuserIdAndType[0].code != user.face) {
                // Remove old face
                driver.face.delete(user.userId)
                // Register new face
                let res = driver.face.registerFaceByPicFile(user.userId, user.face)
                log.info("3. Register face,res:", res)
                if (res != 0) {
                    return faceService.regErrorEnum.picture[res + '']
                }
                let src = "/app/data/user/" + user.userId + "/register.jpg"
                std.ensurePathExists(src)
                // Move the temporary directory for faces to the folder corresponding to user.
                common.systemBrief('mv ' + user.face + " " + src)
                ret = sqliteService.d1_voucher.updatecodeAndExtraByuserIdAndtype(user.userId, "300", src, JSON.stringify({ faceType: 0 }))

            }
        }
    } else {
        // If there is no content, delete it from the database table.
        sqliteService.d1_voucher.deleteByuserIdAndtype(user.userId, "300")
        driver.face.delete(user.userId)
        common.systemBrief("rm -rf /app/data/user/" + user.userId)
    }

    return true
}

// New personnel
screen.insertUser = async function (user) {
    // Start processing vouchers
    const saveVoucher = async (type, code) => {
        if (type == "200") {
            let cardData = sqliteService.d1_voucher.findByCodeAndType(code, "200");
            if (cardData.length > 0 && cardData[0].userId != user.userId) {
                // The option to add the item failed.
                log.info("Present Card again");
                return "localUserAddView.failCardRepeat"
            }
        }
        // When type is "300", a specific method is first called to check whether the credential can continue to be saved.
        if (type === "300") {
            let preCheckResult = await preSaveCheck(code); // Assuming this is the method you mentioned that needs to be called.
            if (preCheckResult !== true) { // If the pre-check fails, return false directly.
                return preCheckResult;
            }
            code = "/app/data/user/" + user.userId + "/register.jpg"
        }

        if (type == "400") {
            let pwdData = sqliteService.d1_voucher.findByCodeAndType(code, "400");
            if (pwdData.length > 0 && pwdData[0].userId != user.userId) {
                // The option to add the item failed.
                log.info("Repeat Password");
                return "localUserAddView.failPwdRepeat"
            }
        }

        let keyId = std.genRandomStr(32);

        let extra = type == 300 ? JSON.stringify({ faceType: 0 }) : JSON.stringify({})
        let voucherRet = await sqliteService.d1_voucher.save({
            keyId: keyId,
            type: type,
            code: code,
            userId: user.userId,
            extra: extra
        });

        if (voucherRet != 0) {
            // If saving credentials fails, the saved user information and any other credentials that may have been saved will be deleted.
            await sqliteService.d1_person.deleteByUserId(user.userId);
            await sqliteService.d1_voucher.deleteByUserId(user.userId);
            return false;
        }
        return true;
    };
    async function preSaveCheck(code) {
        let ret = driver.face.registerFaceByPicFile(user.userId, code)
        log.info("1. Register face,ret:", ret)
        if (ret != 0) {
            return faceService.regErrorEnum.picture[ret + '']
        }
        // After successful registration, you need to move the original images to the corresponding directory for the user account.
        let src = "/app/data/user/" + user.userId + "/register.jpg"
        std.ensurePathExists(src)
        common.systemBrief('mv ' + code + " " + src)
        return true;
    }

    let success = true;
    if (success === true && user.face && !(success = await saveVoucher("300", user.face)));
    if (success === true && user.pwd && !(success = await saveVoucher("400", user.pwd)));
    if (success === true && user.card && !(success = await saveVoucher("200", user.card)));


    if (success === true) {
        //{"id":"423","userId":"423","name":"John","idCard":"123","pwd":"251574","card":"123"}
        // Save personnel information
        let personRet = await sqliteService.d1_person.save({
            userId: user.userId,
            name: user.name,
            extra: JSON.stringify({ type: user.type == 1 ? 1 : 0, idCard: user.idCard })
        });
        if (personRet != 0) {
            sqliteService.d1_voucher.deleteByUserId(user.userId);
            return "localUserAddView.failRepeat"
        }
        // Add a permanent permission
        sqliteService.d1_permission.save({ permissionId: user.userId, userId: user.userId, timeType: 0 })
    } else {
        await sqliteService.d1_voucher.deleteByUserId(user.userId);
    }

    return success;

}

// Obtain local personnel information
screen.getVoucher = function (userId) {

    let person = sqliteService.d1_person.find({ userId: userId });

    if (person.length < 0) {
        return
    }
    let pwd_voucher = sqliteService.d1_voucher.find({ userId: userId, type: "400" })[0] || undefined
    let card_voucher = sqliteService.d1_voucher.find({ userId: userId, type: "200" })[0] || undefined
    let face_voucher = sqliteService.d1_voucher.find({ userId: userId, type: "300" })[0] || undefined
    let idCard_voucher
    try {
        idCard_voucher = JSON.parse(person[0].extra).idCard
    } catch (error) {
    }

    return {
        id: userId,
        idCard: idCard_voucher ? idCard_voucher : undefined,
        card: card_voucher ? card_voucher.code : undefined,
        pwd: pwd_voucher ? pwd_voucher.code : undefined,
        face: face_voucher ? face_voucher.code : undefined,
        type: JSON.parse(person[0].extra).type
    }

}

screen.getUsers = function (page = 0, size = 6, userId, name) {
    if (userId || name) {
        let user = sqliteService.d1_person.findByUserId(userId)[0]
        if (user) {
            user.id = user.userId
            return { data: [user], totalPage: 1, totalSize: 1, currentPage: 1 }
        }
        // Usernames may be duplicated.
        let users = sqliteService.d1_person.findByName(name)
        if (users && users.length > 0) {
            users.map(v => {
                v.id = v.userId
            })
            function chunkArray(arr, size) {
                // If the array is empty or has a size of zero, return an empty array.
                if (arr.length === 0 || size <= 0) {
                    return [];
                }
                const result = [];
                // Use a loop to iterate through the array and cut it into smaller segments according to size.
                for (let i = 0; i < arr.length; i += size) {
                    result.push(arr.slice(i, i + size));  // The slice function extracts a specified range of elements.
                }
                return result;
            }
            const chunkedArray = chunkArray(users, size);
            return { data: chunkedArray[page], totalPage: Math.ceil(users.length / size), totalSize: users.length, currentPage: page + 1 }
        }
        return { data: [], totalPage: 0, totalSize: 0, currentPage: 1 }
    }
    let userCount = sqliteService.d1_person.count()
    let users = sqliteService.d1_person.findOrderByUserIdAsc({ page, size })
    if (users.length > 0) {
        users.forEach(element => { element.id = element.userId });
    }
    // Total pages
    let totalPage = Math.ceil(userCount / size)
    return { data: users, totalPage: totalPage, totalSize: userCount, currentPage: page + 1 }
}

// Get Passage Record
screen.getPassRecord = function (page = 0, size = 6) {
    let passCount = sqliteService.d1_pass_record.count()
    let datas = sqliteService.d1_pass_record.findOrderByTimeDesc({ page, size })
    // Total pages
    let totalPage = Math.ceil(passCount / size)
    return { data: datas, totalPage: totalPage, totalSize: passCount, currentPage: page + 1 }
}

// Face registration begins, UI control
screen.faceEnterStart = function (userId) {
    dxMap.get("UI").put("faceEnterStart", userId)
    driver.face.status(1)
    driver.face.mode(1)
}

// Face registration complete, UI control
screen.faceEnterEnd = function () {
    dxMap.get("UI").del("faceEnterStart")
    driver.face.status(0)
    // driver.face.mode(0)
}

// Get Card Number UI Control
screen.getCardStart = function () {
    dxMap.get("UI").put("getCardStart", true)
}

// The UI control for obtaining the card number ends.
screen.endCardEnd = function () {
    dxMap.get("UI").del("getCardStart")
}

// Enable facial recognition
screen.faceRecgStart = function () {
    driver.face.status(1)
    driver.face.mode(0)
}

// Facial recognition paused
screen.faceRecgPause = function () {
    driver.face.status(0)
}

// Face recognition results
screen.faceEnterResult = function (facePic) {
    if (facePic) {
        faceEnterView.successFlag = true
        // Success, face photo displayed.
        localUserAddView.addFace(facePic)
        dxui.loadMain(localUserAddView.screenMain)
        faceEnterView.backCb()
    } else {
        // Failure, error message
        faceEnterView.timeout()
    }
}

//  Face authentication begins on non-recognition pages, controlled by the UI.
screen.faceAuthStart = function () {
    dxMap.get("UI").put("faceAuthStart", "Y")
    driver.face.status(1)
    driver.face.mode(0)
}

// Face authentication ends on non-recognition pages, UI control
screen.faceAuthEnd = function () {
    dxMap.get("UI").del("faceAuthStart")
    driver.face.status(0)
}

// Face authentication results on non-recognition page
screen.faceAuthResult = function (bool) {
    if (bool) {
        // Success, you have entered the settings menu.
        driver.alsa.play(`/app/code/resource/${config.get("base.language") == "EN" ? "EN" : "EN"}/wav/recg_s.wav`)
        dxui.loadMain(configView.screenMain)
    } else {
        // Failure, error message
        driver.alsa.play(`/app/code/resource/${config.get("base.language") == "EN" ? "EN" : "EN"}/wav/recg_f.wav`)
        identityVerificationView.statusPanel.fail()
    }
}

// Save configuration
screen.saveConfig = function (configAll) {
    if (configAll && configAll.net) {
        // Check if both SSID and PSK exist.
        if (configAll.net.ssid || configAll.net.psk) {
            // Add your additional actions here.
            bus.fire("setConfig", configAll)
            return true
        }
    }
    return configService.configVerifyAndSave(configAll)
}

// Get configuration
screen.getConfig = function () {
    let config1 = config.getAll()
    return config1
}

//  Password access
screen.pwdAccess = function (pwd) {
    bus.fire("access", { data: { type: "400", code: pwd } })
}

// Switch network type
screen.switchNetworkType = function (data) {
    bus.fire("switchNetworkType", data)
}

// Get WiFi list
screen.netGetWifiSsidList = function () {
    bus.fire("netGetWifiSsidList")
}

screen.netWifiSsidList = function (data) {
    if (data.length == 0 && config.get("net.type") == 2) {
        // Wi-Fi
        std.setTimeout(() => {
            screen.netGetWifiSsidList()
        }, 1000)
        return
    }
    networkSettingView.wifiListData = data
    networkSettingView.wifiList.refresh()
}

// Connect to Wi-Fi
screen.netConnectWifiSsid = function (ssid, psk) {
    return driver.net.netConnectWifiSsid(ssid, psk)
}

// Get Card Number
screen.getCard = function (card) {
    localUserAddView.cardBoxInput.text(card)
}

// bus event
function busEvents() {
    // Network status
    bus.on('netStatus', (data) => {
        console.log(JSON.stringify(data));
        let type = config.get("net.type")
        if (data.connected) {
            let ip = net.getModeByCard(type).param.ip
            mainView.ipLbl.text("IP:" + ip)
            config.setAndSave("net.ip", ip)
            config.setAndSave("net.mac", net.getMacaddr(type))
            topView.ethConnectState(true, type)
            networkSettingView.netInfo[10].label.dataI18n = "networkSettingView.networkConnected"
        } else {
            topView.ethConnectState(false, type)
            networkSettingView.netInfo[10].label.dataI18n = "networkSettingView.networkUnconnected"
        }
        i18n.refreshObj(networkSettingView.netInfo[10].label)
    })
    // MQTT connection status
    bus.on('mqttStatus', (data) => {
        if (data == "connected") {
            topView.mqttConnectState(true)
        } else {
            topView.mqttConnectState(false)
        }
    })
    bus.on("beginAddFace", screen.beginAddFace)
    bus.on("faceEnterResult", screen.faceEnterResult)
    bus.on("exitIdle", screen.exitIdle)
    bus.on("netGetWifiSsidList", screen.netGetWifiSsidList)
    bus.on("getCard", screen.getCard)
    bus.on("faceAuthResult", screen.faceAuthResult)
    bus.on("accessRes", screen.accessRes)
    // bus.on("trackUpdate", screen.trackUpdate)
    bus.on("hideSn", screen.hideSn)
    bus.on("changeLanguage", screen.changeLanguage)
    bus.on("hideIp", screen.hideIp)
    bus.on("screenManagerRefresh", screen.screenManagerRefresh)
    bus.on("netWifiSsidList", screen.netWifiSsidList)
    bus.on("appMode", screen.appMode)
    bus.on("upgrade", screen.upgrade)
    // bus.on("cardReset", screen.cardReset)
    bus.on("trackResult", screen.trackResult)
}

let setTimeout
screen.cardReset = function (msg) {
    if (msg.type == 2 && msg.status == 3) {
        setTimeout = std.setTimeout(() => {
            driver.net.cardReset()
        }, 30 * 1000);
    } else {
        if (setTimeout) {
            std.clearTimeout(setTimeout)
        }
    }
}

// Start registering your face
screen.beginAddFace = function (data) {
    log.info('screen.beginAddFace', JSON.stringify(data));

    if (!data.fileName) {
        return screen.faceEnterResult()
    }

    driver.alsa.play(`/app/code/resource/${config.get("base.language") == "EN" ? "EN" : "EN"}/wav/recognition_s.wav`)
    faceEnterView.statusPanel.success("faceEnterView.recogSuccess")
    // Save the image to your local device   
    let src = `/app/data/user/register.jpg`
    common.systemBrief(`mv ${data.fileName} ${src}`)
    common.systemBrief(`rm -rf /app/data/user/temp/*`)

    screen.faceEnterResult(src)
}

// Success/Failure
screen.accessRes = function (bool) {
    if (bool) {
        mainView.statusPanel.success()
    } else {
        mainView.statusPanel.fail()
    }
}

// Switch app mode
screen.appMode = function (mode) {
    if (mode == 0) {
        // Switch to standard
        mainView.menuBtnBox.show()
        if (config.get("base.showProgramCode") == 1) {
            mainView.appBtnBox.show()
            deviceInfoView.sysInfo[3].obj.show()
        } else {
            mainView.appBtnBox.hide()
            deviceInfoView.sysInfo[3].obj.hide()
        }
        if (config.get("sys.pwd") == 1) {
            mainView.pwdBtnBox.show()
        } else {
            mainView.pwdBtnBox.hide()
        }
        mainView.miniBkgBox.hide()
    } else if (mode == 1) {
        // Switch to concise mode
        mainView.miniBkgBox.show()
        if (config.get("base.showProgramCode") == 1) {
            mainView.minAppBtnImg.show()
            deviceInfoView.sysInfo[3].obj.show()
        } else {
            mainView.minAppBtnImg.hide()
            deviceInfoView.sysInfo[3].obj.hide()
        }
        if (config.get("sys.pwd") == 1) {
            mainView.minPwdBtnImg.show()
        } else {
            mainView.minPwdBtnImg.hide()
        }
        mainView.menuBtnBox.hide()
    }
}

/**
 * 
 * @param {object} data Coordinate information
 * @param {number} id face_id is used to associate and identify the name.
 * @param {bool} isLiving Is it alive?
 */
screen.trackUpdate = function (data, id, isLiving) {
    let item = mainView.trackFaces[0]
    for (let i = 0; i < 10; i++) {
        let ele = mainView.trackFaces[i]
        if (ele.face_id == id) {
            item = ele
            break
        }
    }
    item.face_id = id

    if (item && item.timer) {
        std.clearTimeout(item.timer)
        item.timer = null
    }

    item.timer = std.setTimeout(() => {
        item.trackFace.hide()
        // item.trackFaceName.hide()
        if (item.timer) {
            std.clearTimeout(item.timer)
            item.timer = null
        }
    }, 300)

    let edge = data.w > data.h ? data.w : data.h
    let offset = Math.abs(data.w - data.h) / 2
    item.trackFace.show()
    item.trackFace.setSize(edge, edge)
    item.trackFace.radius(edge / 2)
    if (data.w > data.h) {
        item.trackFace.setPos(data.x, data.y - offset)
    } else {
        item.trackFace.setPos(data.x - offset, data.y)
    }

    item.trackFaceName.text(" ")

    if (item.result && item.result.result === true && item.result.id == id) {
        item.trackFace.setBorderColor(viewUtils.color.success)
        let user = sqliteService.d1_person.findByUserId(item.result.userId)[0]
        item.trackFaceName.text(user ? user.name : "")
    } else if (item.result && item.result.result === false && item.result.id == id) {
        item.trackFace.setBorderColor(viewUtils.color.fail)
    } else if (isLiving) {
        item.trackFace.setBorderColor(0xf3e139)
    } else {
        item.trackFace.setBorderColor(0xffffff)
    }
}

// Authentication results
screen.trackResult = function (data) {
    for (let i = 0; i < 10; i++) {
        let ele = mainView.trackFaces[i]
        if (ele.face_id == data.id) {
            ele.result = data
            return
        }
    }
}

screen.hideSn = function (bool) {
    if (bool) {
        mainView.bottomSnBtn.show()
    } else {
        mainView.bottomSnBtn.hide()
    }
}

screen.hideIp = function (bool) {
    if (bool) {
        mainView.ipLbl.show()
    } else {
        mainView.ipLbl.hide()
    }
}

screen.hideBottomBox = function (bool) {
    if (bool) {
        mainView.bottomBox.hide()
    } else {
        mainView.bottomBox.show()
    }
}

screen.changeLanguage = function () {
    i18n.setLanguage(screen.getConfig()['base.language'])
}

screen.upgrade = function (data) {
    const { title, content } = data
    viewUtils.confirmOpen(title, content)
}

export default screen
